package com.miao.test.common;

import com.alibaba.fastjson.annotation.JSONField;
import com.miao.test.common.enums.MessageType;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Data;

/**
 * @Auther: miaoguoxin
 * @Date: 2021/2/26 09:27
 * @Description:
 */
@Data
public class Message {
    /**头长度*/
    private int headerLength;
    /**版本号*/
    private int version;
    /**{@link MessageType}*/
    private int messageType;
    /**请求序号*/
    private long sequence;
    /**指令类型 {@link com.miao.test.common.enums.Command}*/
    private int commandType;
    /**消息体长度*/
    private int bodyLength;
    /**消息体*/
    private byte[] body;
    @JSONField(serialize = false, deserialize = false)
    private ByteBuf byteBuf;

    public Message() {
    }

    public static Message writeRequest(int version, long sequence, int commandType, byte[] body) {
        Message message = new Message(version, sequence, MessageType.REQ.getCode(), commandType, body);
        message.writeBuffer();
        return message;
    }

    public static Message writeResponse(int version, long sequence, int commandType, byte[] body) {
        Message message = new Message(version, sequence, MessageType.RES.getCode(), commandType, body);
        message.writeBuffer();
        return message;
    }

    public static Message read(ByteBuf byteBuf) {
        return new Message(byteBuf);
    }

    protected Message(ByteBuf byteBuf) {
        this.headerLength = byteBuf.readInt();
        this.version = byteBuf.readInt();
        this.messageType = byteBuf.readInt();
        this.sequence = byteBuf.readLong();
        this.commandType = byteBuf.readInt();
        this.bodyLength = byteBuf.readInt();
        this.body = new byte[byteBuf.readableBytes()];
        byteBuf.readBytes(this.body);
        this.byteBuf = byteBuf;
    }

    protected Message(int version, long sequence, int messageType, int commandType, byte[] body) {
        this.version = version;
        this.sequence = sequence;
        this.messageType = messageType;
        this.commandType = commandType;
        this.bodyLength = body.length;
        this.body = body;
    }


    private void writeBuffer() {
        this.byteBuf = Unpooled.directBuffer(Constant.HEADER_LENGTH + bodyLength);
        this.byteBuf.writeInt(this.headerLength);
        this.byteBuf.writeInt(this.version);
        this.byteBuf.writeInt(this.messageType);
        this.byteBuf.writeLong(this.sequence);
        this.byteBuf.writeInt(this.commandType);
        this.byteBuf.writeInt(this.bodyLength);
        this.byteBuf.writeBytes(this.body);
    }
}
